#include "Buffer.h"
#include "ace/OS.h"

bool g_Verbal = true;

Buffer::Buffer(int Size) : m_Data(Size),m_TotalSize(Size),m_CurrPos(0),m_UsedSize(0)
{

}

#ifdef BIG_ENDIAN
long
swaplong(long x)
{
	return ((x>>24) & 0xFF) | ((x>>16) & 0xFF) | ((x>>8) & 0xFF) | (x & 0xFF);
}
#endif

Buffer::Buffer(FILE* file) : m_CurrPos(0),m_UsedSize(0)
{
	int Res;
	m_TotalSize = 0;

	Res = fread(&m_TotalSize,4,1,file);
	if (!Res)
		throw "Failed to read block size";

#ifdef BIG_ENDIAN
	m_TotalSize = swaplong(m_TotalSize);
#endif

	if (!m_TotalSize)
		throw "Total size of block is 0";

	m_UsedSize = m_TotalSize;
	m_TotalSize += 500;
	m_Data.resize(m_TotalSize);
	
	Res = fread(m_Camera,12,1,file);
	if (!Res)
		throw  "Failed to read camera angles";


	Res = fread(&(m_Data[0]),m_UsedSize,1,file);
	if (!Res)
		throw "Failed to read data";


}

bool Buffer::Write(FILE* file)
{
	int Res;
	m_TotalSize = 0;

	Res = fwrite(&m_UsedSize,4,1,file);
	if (!Res)
		return false;

	Res = fwrite(m_Camera,12,1,file);
	if (!Res)
		return false;

	Res = fwrite(&(m_Data[0]),m_UsedSize,1,file);
	if (!Res)
		return false;
	return true;

}


Buffer::~Buffer()
{
}


byte Buffer::GetByte() const
{
	return m_Data[m_CurrPos++];
}
unsigned short Buffer::GetShort(bool Invert) const
{
	unsigned short B1 = GetByte();
	unsigned short B2 = GetByte();

	unsigned short Ret = (B2 << 8) | B1;
	
	if (Invert)
		Ret = ntohs(Ret);

	return Ret;
}

unsigned long Buffer::GetLong(bool Invert) const
{
	unsigned long S1 = GetShort();
	unsigned long S2 = GetShort();
	unsigned long Ret = (S2 << 16) | S1;
	
	if (Invert)
		Ret = ntohl(Ret);

	return Ret;
}


float Buffer::GetFloat() const
{
	unsigned long Temp = GetLong();
	return *((float*)&Temp);
}


std::string Buffer::GetString() const
{
	std::string RetVal = (char*)(&m_Data[m_CurrPos]);
	m_CurrPos += RetVal.length() + 1;
	return RetVal;
}



void Buffer::PutByte(byte c)
{
	m_Data[m_CurrPos] = c;
	m_CurrPos++;
	if (m_CurrPos > m_UsedSize)
		m_UsedSize++;
}

void Buffer::PutShort(unsigned short c,bool Invert)
{
	if (Invert)
		c = ntohs(c);

	byte B1 = (c >> 8) & 0xFF;
	byte B2 = c & 0xFF;
	PutByte(B2);
	PutByte(B1);
}

void Buffer::PutLong(unsigned long c,bool Invert)
{
	if (Invert)
		c = ntohl(c);

	short S1 = (c>>16) & 0xFFFF;
	short S2 = c & 0xFFFF;
	PutShort(S2);
	PutShort(S1);
}

void Buffer::PutFloat(float c)
{
	long Temp = *((long*)&c);
	PutLong(Temp);
}

void Buffer::PutString(std::string S)
{
	strcpy((char*)(&m_Data[m_CurrPos]),S.c_str());
	m_CurrPos += S.length() + 1;
	if (m_CurrPos > m_UsedSize)
		m_UsedSize += S.length() + 1;
}

void Buffer::WriteTo(Buffer& other,int Size)
{
	if (Size == -1 || Size > (m_UsedSize - m_CurrPos))
		Size = m_UsedSize - m_CurrPos;
	other.m_UsedSize += Size;
	memcpy(&other.m_Data[other.m_CurrPos],&m_Data[m_CurrPos],Size);
	other.m_CurrPos += Size;
	m_CurrPos += Size;
}

Buffer& Buffer::operator=(const Buffer& other)
{
	if (&other != this)
	{
		m_CurrPos = other.m_CurrPos;
		m_TotalSize = other.m_TotalSize;
		m_UsedSize = other.m_UsedSize;

		for (int I = 0; I < 3; I++)
			m_Camera[I] = other.m_Camera[I];

		m_Data = other.m_Data;
	}
	return *this;
}


void Buffer::SetCameraAngs(float Angs[3])
{
	for (int I = 0; I < 3; I++)
	{
		m_Camera[I] = Angs[I];
	}
}
